package org.wpahs.ahn.rssfeed;

import android.content.Context;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.app.Activity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Base64;
import android.util.Log;

import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.wpahs.ahn.rssfeed.DB.DBMyFeed;

import java.util.ArrayList;

import java.util.List;



/**
 * Fragment used for managing interactions for and presentation of a navigation drawer.
 * See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
 * design guidelines</a> for a complete explanation of the behaviors implemented here.
 */
public class NavigationDrawerFragment extends Fragment {

    /**
     * Remember the position of the selected item.
     */
    private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";

    /**
     * Per the design guidelines, you should show the drawer on launch until the user manually
     * expands it. This shared preference tracks this.
     */
    private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";

    /**
     * A pointer to the current callbacks instance (the Activity).
     */
    private NavigationDrawerCallbacks mCallbacks;

    /**
     * Helper component that ties the action bar to the navigation drawer.
     */
    private ActionBarDrawerToggle mDrawerToggle;

    private DrawerLayout mDrawerLayout;
    public ListView mDrawerListView;
    private View mFragmentContainerView;

    private int mCurrentSelectedPosition = -1;
    private int mCurrentSelectedFeed=0;
    private boolean mFromSavedInstanceState;
    private boolean mUserLearnedDrawer;
    private MyFeedAdapter mAdapter;
    private SparseArray<Bitmap> mBitmaps = new SparseArray<>();

    private List<MyFeed> feeds = new ArrayList<>();

    public NavigationDrawerFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Read in the flag indicating whether or not the user has demonstrated awareness of the
        // drawer. See PREF_USER_LEARNED_DRAWER for details.
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);

        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        }

        // Select either the default item (0) or the last selected item.
        //selectItem(mCurrentSelectedPosition);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Indicate that this fragment would like to influence the set of actions in the action bar.
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mDrawerListView = (ListView) inflater.inflate(
                R.layout.fragment_navigation_drawer, container, false);
        mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                selectItem(position);
            }
        });


        return mDrawerListView;
    }

    private int findPosition(int feedId){
        int position = -1;
        for(int idx=0; idx< feeds.size(); idx++){
            if(feeds.get(idx).getId() == feedId){
                return idx;
            }
        }
        return position;
    }

    public void loadUserFeeds(){
        Context context = getActivity();

        DBMyFeed fs = new DBMyFeed(context);
        List<MyFeed> tempFeeds =fs.GetFeeds(true);
        fs.close();
        mDrawerListView.setEnabled(false);
        feeds.clear();
        for(MyFeed f : tempFeeds){
            feeds.add(f);
        }
        try{

        if(mAdapter==null){
            mAdapter = new MyFeedAdapter(
                    getActionBar().getThemedContext(),R.layout.navmenuitem_layout,
                    feeds
            );
        }

        mDrawerListView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
        mDrawerListView.invalidateViews();

        int indexToSelect =  findPosition(mCurrentSelectedFeed);

        if(indexToSelect == -1){
            // it's not there anymore.  Find All
            mCurrentSelectedFeed = findPosition(0);
            selectItem(mCurrentSelectedFeed);
        }else{
            mCurrentSelectedFeed = indexToSelect;
        }
            mDrawerListView.setEnabled(true);

            selectItem(mCurrentSelectedFeed);

        }catch (Exception ex){
            Toast.makeText(context,ex.getMessage(),Toast.LENGTH_LONG).show();
        }finally {
            mDrawerListView.setEnabled(true);

        }

    }

    public void setFavicon(int feedId){
        DBMyFeed dbf = new DBMyFeed(getActivity());
        MyFeed feed =dbf.getFeed(feedId);
        Bitmap bitmap = decodeBase64(feed.getImage());
        int position = this.findPosition(feedId);
        View v = mDrawerListView.getChildAt(position);
        if(bitmap !=null) {
            mBitmaps.put(feedId, bitmap);
        }
        if(v != null){
            FeedHolder fh = (FeedHolder)v.getTag();
            if(fh != null){
                fh.tvName.setText(feed.getTitle());
                if(bitmap != null) {
                    fh.ivImage.setImageBitmap(bitmap);
                }else {
                    fh.ivImage.setImageResource(R.drawable.ic_action_web_site);
                }
                mDrawerListView.invalidateViews();
            }

        }
    }

    private Bitmap decodeBase64(String input) {
        Bitmap retval = null;
        if(input != null) {
            byte[] decodedByte = Base64.decode(input, 0);
            retval =  BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
        }
        return retval;
    }

    public boolean isDrawerOpen() {
        return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
    }

    /**
     * Users of this fragment must call this method to set up the navigation drawer interactions.
     *
     * @param fragmentId   The android:id of this fragment in its activity's layout.
     * @param drawerLayout The DrawerLayout containing this fragment's UI.
     */
    public void setUp(int fragmentId, DrawerLayout drawerLayout) {
        mFragmentContainerView = getActivity().findViewById(fragmentId);
        mDrawerLayout = drawerLayout;

        // set a custom shadow that overlays the main content when the drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        // set up the drawer's list view with items and click listener

        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions
        // between the navigation drawer and the action bar app icon.

        mDrawerToggle = new ActionBarDrawerToggle(
                getActivity(),                    /* host Activity */
                mDrawerLayout,                    /* DrawerLayout object */
                R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
                R.string.navigation_drawer_close  /* "close drawer" description for accessibility */
        ) {
            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                if (!isAdded()) {
                    return;
                }

                getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                if (!isAdded()) {
                    return;
                }

                if (!mUserLearnedDrawer) {
                    // The user manually opened the drawer; store this flag to prevent auto-showing
                    // the navigation drawer automatically in the future.
                    mUserLearnedDrawer = true;
                    SharedPreferences sp = PreferenceManager
                            .getDefaultSharedPreferences(getActivity());
                    sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
                }

                getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
            }
        };

        // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
        // per the navigation drawer design guidelines.
        if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
            mDrawerLayout.openDrawer(mFragmentContainerView);
        }

        // Defer code dependent on restoration of previous instance state.
        mDrawerLayout.post(new Runnable() {
            @Override
            public void run() {
                mDrawerToggle.syncState();
            }
        });

        mDrawerLayout.setDrawerListener(mDrawerToggle);

        loadUserFeeds();

        if(mCurrentSelectedPosition == -1){
            mCurrentSelectedFeed = 0;
            mCurrentSelectedPosition = findPosition(mCurrentSelectedFeed);
            mDrawerListView.getAdapter().getItem(0);
            mDrawerListView.setItemChecked(mCurrentSelectedPosition,true);
            selectItem(mCurrentSelectedPosition);
        }

    }

    public void updateFeedItem(int feedId){
        DBMyFeed db = new DBMyFeed(this.getActivity());
        MyFeed mf = db.getFeed(feedId);
        if(mf != null){
            for(int idx=0; idx<feeds.size(); idx++){
                MyFeed f = feeds.get(idx);
                if(f.getId()== feedId){
                    f.setTitle(mf.getTitle());
                    f.setSubtitle(mf.getSubtitle());
                    mDrawerListView.invalidateViews();
                    break;
                }
            }
        }
    }

    public void selectItem(int position) {
        mCurrentSelectedPosition = position;
        mCurrentSelectedFeed = feeds.get(position).getId();
        if (mDrawerListView != null) {

            mDrawerListView.setItemChecked(position, true);
        }
        if (mDrawerLayout != null) {
            mDrawerLayout.closeDrawer(mFragmentContainerView);
        }
        if (mCallbacks != null) {
            if(feeds != null && position <feeds.size()) {
                mCallbacks.onNavigationDrawerItemSelected(feeds.get(position),position);
            }
        }
    }

    public void removeFeed(int feedid,boolean jumpToAllAfterRemoval){
        try {

            int position = findPosition(feedid);
            if(position >=0) {
                feeds.remove(position);
                mAdapter.notifyDataSetChanged();
                mDrawerListView.invalidateViews();
                if (jumpToAllAfterRemoval) {
                    selectItem(findPosition(0));
                }
            }
        }catch (Exception ex){
            Log.e("removeFeed",ex.getMessage());
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallbacks = (NavigationDrawerCallbacks) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Forward the new configuration the drawer toggle component.
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // If the drawer is open, show the global app actions in the action bar. See also
        // showGlobalContextActionBar, which controls the top-left area of the action bar.
        if (mDrawerLayout != null && isDrawerOpen()) {
            inflater.inflate(R.menu.global, menu);
            showGlobalContextActionBar();
        }
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       return mDrawerToggle.onOptionsItemSelected(item);
    }

    /**
     * Per the navigation drawer design guidelines, updates the action bar to show the global app
     * 'context', rather than just what's in the current screen.
     */
    private void showGlobalContextActionBar() {
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(true);
        //actionBar.setNavigationMode(ActionBar.);
        actionBar.setTitle(R.string.app_name);
    }

    private ActionBar getActionBar() {
        return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }

    /**
     * Callbacks interface that all activities using this fragment must implement.
     */
    public static interface NavigationDrawerCallbacks {
        /**
         * Called when an item in the navigation drawer is selected.
         */
        void onNavigationDrawerItemSelected(MyFeed feed,int position);
    }

    public Bitmap getFeedBitmap(int feedId){
        return  mBitmaps.get(feedId,null);
    }

    static class FeedHolder {
        ImageView ivImage;
        TextView tvName;
        int position;
        int feedId;
    }

    private class MyFeedAdapter extends ArrayAdapter<MyFeed> {
        Context mContext;

        public MyFeedAdapter(Context context, int resource, List<MyFeed>objects) {
            super(context, resource, objects);
            setRetainInstance(true);
            mContext = context;

        }

        @Override
        public View getView(int position, View v, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            FeedHolder holder;
            MyFeed myFeed = this.getItem(position);
            if(v == null){
                v = inflater.inflate(R.layout.navmenuitem_layout,parent,false);
                holder = new FeedHolder();
                holder.ivImage = (ImageView)v.findViewById(R.id.navmenu_image);
                holder.tvName = (TextView)v.findViewById(R.id.navmenuitem_name);
            }else{
                holder = (FeedHolder)v.getTag();
            }
            holder.position=position;
            holder.feedId = myFeed.getId();
            v.setTag(holder);

            if(holder.ivImage != null){
                Bitmap bitMap = mBitmaps.get(myFeed.getId(),null);
                if(bitMap == null){
                    String image =  myFeed.getImage();
                    bitMap = decodeBase64(image);
                    mBitmaps.put(myFeed.getId(),bitMap);
                }

                if(bitMap != null){
                    holder.ivImage.setImageBitmap(bitMap);
                }else{
                    // check it's id.  if it's favorites.  We need to add the star
                    if(myFeed.getId() == -2){ //favorites
                        holder.ivImage.setImageResource(R.drawable.ic_action_good_menu);

                    }else if(myFeed.getId() == -1){
                        holder.ivImage.setImageResource(R.drawable.ic_action_settings);
                    }else if(myFeed.getId() == 0){
                        holder.ivImage.setImageResource(R.drawable.ic_action_select_all);
                    }
                }
            }

            holder.tvName.setText((myFeed.getTitle() == null ? myFeed.getUrl() : myFeed.getTitle()));
            return v;
        }


    }



}
